package com.redare.dev.smart.generator.service.impl;

import com.redare.dev.smart.generator.sdk.CommonSdk;
import com.redare.dev.smart.generator.sdk.pojo.*;
import com.redare.dev.smart.generator.sdk.pojo.form.OnlFormFieldForm;
import com.redare.dev.smart.generator.sdk.pojo.form.OnlFormHeadForm;
import com.redare.dev.smart.generator.sdk.utils.BuilderUtil;
import com.redare.dev.smart.generator.sdk.utils.VelocityUtil;
import com.redare.dev.smart.generator.service.constant.Defaults;
import com.redare.dev.smart.generator.service.provider.FileProviderFactory;
import com.redare.dev.smart.generator.service.service.OnlFormFieldService;
import com.redare.dev.smart.generator.service.service.OnlFormHeadService;
import com.redare.dev.smart.generator.service.utils.GlobalDataHelper;
import com.redare.devframework.common.pojo.CommonResult;
import com.redare.devframework.common.validation.ValidationUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.velocity.VelocityContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author yangqy on 2021/9/17
 * @date 2021/9/17 下午5:22
 */
@Service(value = "com.redare.dev.smart.generator.impl.CommonSdkImpl")
public class CommonSdkImpl implements CommonSdk {

    @Autowired
    OnlFormHeadService onlFormHeadService;

    @Autowired
    OnlFormFieldService onlFormFieldService;

    @Override
    public CommonResult<Boolean> syncTable() {
        return null;
    }

    @Override
    public CommonResult<List<CodeRoot>> getCodeRoots() {
        List<CodeRoot> roots = GlobalDataHelper.getInstance().getTemplates().getRoots();
        return CommonResult.returnDataWrapper(roots);
    }

    @Override
    public CommonResult<Boolean> codeGenerate(CodeGenForm.CodeGen form) {
        CommonResult result = ValidationUtils.simpleValidate(form);
        if (result.isNotSuccess()) {
            return result;
        }
//        List<String> selectGroups = new ArrayList<>();
//        for (CodeGroup group : GlobalDataHelper.getInstance().getTemplates().getRoots().get(0).getGroups()) {
//            selectGroups.add(group.getId());
//        }
//        List<OnlFormHead> onlFormHeadList = onlFormHeadService.findOnlFormHeadList(new OnlFormHeadForm.Search().setIncludeFields(true));
        List<OnlFormHead> onlFormHeadList = form.getOnlFormHeads();
        List<OnlFormHead> children = new ArrayList<>();
        for (OnlFormHead formHead : onlFormHeadList) {
            String subTableStr = formHead.getSubTableStr();
            //子表处理
            if (StringUtils.isNotBlank(subTableStr)&&formHead.getTableType()==1){
                String[] subTables = subTableStr.split(",");
                for (String s : subTables) {
                    OnlFormHead onlFormHead = onlFormHeadService.getOnlFormHead(new OnlFormHeadForm.Get().setTableName(s));
                    List<OnlFormField> onlFormFieldList = onlFormFieldService.findOnlFormFieldList(new OnlFormFieldForm.Search().setFormHeadId(onlFormHead.getId()));
                    onlFormHead.setFields(onlFormFieldList);
                    children.add(onlFormHead);
                }
                formHead.setChildren(children);
            }
            List<OnlFormField> onlFormFieldList = onlFormFieldService.findOnlFormFieldList(new OnlFormFieldForm.Search().setFormHeadId(formHead.getId()));
            formHead.setFields(onlFormFieldList);
        }
        onlFormHeadList.addAll(children);
        List<String> ignoreList = new ArrayList<>();
        if (StringUtils.isNotBlank(GlobalDataHelper.getInstance().getVariables().getIgnoreFields())) {
            ignoreList = com.redare.dev.smart.generator.sdk.utils.StringUtils.splitToList(GlobalDataHelper.getInstance().getVariables().getIgnoreFields(), ",", true);
        }
        for (OnlFormHead formHead : onlFormHeadList) {
            List<OnlFormField> fieldsList = new ArrayList();
            List<OnlFormField> fields = formHead.getFields();
            for (OnlFormField field : fields) {
                // 过滤
                assert ignoreList != null;
                if (!ignoreList.contains(field.getDbFieldName().toUpperCase().trim())) {
                    fieldsList.add(field);
                }
            }
            formHead.setFields(fieldsList);
        }
        generator(form.getGroupIds(), onlFormHeadList, form.getGroupPathMap());
        return CommonResult.returnDataWrapper(null);
    }

    @Override
    public CommonResult<String> codePreview(CodeGenForm.CodePreview form) {
        CommonResult result = ValidationUtils.simpleValidate(form);
        if (result.isNotSuccess()) {
            return result;
        }
        OnlFormHead formHead = form.getOnlFormHead();
        String subTableStr = formHead.getSubTableStr();
        //子表处理
        if (StringUtils.isNotBlank(subTableStr)){
            String[] subTables = subTableStr.split(",");
            List<OnlFormHead> children = new ArrayList<>();
            for (String s : subTables) {
                OnlFormHead onlFormHead = onlFormHeadService.getOnlFormHead(new OnlFormHeadForm.Get().setTableName(s));
                List<OnlFormField> onlFormFieldList = onlFormFieldService.findOnlFormFieldList(new OnlFormFieldForm.Search().setFormHeadId(onlFormHead.getId()));
                onlFormHead.setFields(onlFormFieldList);
                children.add(onlFormHead);
            }
            formHead.setChildren(children);
        }
        List<OnlFormField> onlFormFieldList = onlFormFieldService.findOnlFormFieldList(new OnlFormFieldForm.Search().setFormHeadId(formHead.getId()));
        formHead.setFields(onlFormFieldList);
        List<String> ignoreList = new ArrayList<>();
        if (StringUtils.isNotBlank(GlobalDataHelper.getInstance().getVariables().getIgnoreFields())) {
            ignoreList = com.redare.dev.smart.generator.sdk.utils.StringUtils.splitToList(GlobalDataHelper.getInstance().getVariables().getIgnoreFields(), ",", true);
        }
        List<OnlFormField> fieldsList = new ArrayList();
        List<OnlFormField> fields = formHead.getFields();
        for (OnlFormField field : fields) {
            // 过滤
            assert ignoreList != null;
            if (!ignoreList.contains(field.getDbFieldName().toUpperCase().trim())) {
                fieldsList.add(field);
            }
        }
        formHead.setFields(fieldsList);
        String code = getGenCode(form.getTemplateId(), formHead, null);
        return CommonResult.returnDataWrapper(code);
    }


    public void generator(List<String> groups, List<OnlFormHead> contexts, Map<String, String> groupPathMap) {
        Map<String, Object> params = new HashMap<>();
        params.putAll(Defaults.getDefaultVariables());
        GlobalDataHelper instance = GlobalDataHelper.getInstance();
        params.putAll(instance.getVariables().getParams());

        final List<CodeGroup> groupList = new ArrayList<>();
        instance.getTemplates().getRoots().forEach(it -> groupList.addAll(it.getGroups()));

        final List<CodeGroup> genGroups = groupList.stream().filter(it -> groups.contains(it.getId())).sorted(new ComparatorUtil()).collect(Collectors.toList());
        // start your process
        for (CodeGroup group : genGroups) {

            // process running ..


            String s = groupPathMap.get(group.getId());
            String basePackage = s.substring(s.lastIndexOf("/") + 1);
            String outputPath = s.replace(".", "/");
//            String outputPath = "/Users/yangqiangyu/Downloads/code";
            if (StringUtils.isNotEmpty(outputPath)) {
                for (OnlFormHead context : contexts) {
                    for (CodeTemplate codeTemplate : group.getTemplates()) {
//                        progressIndicator.setText(String.format("generator template %s ...", codeTemplate.getDisplay()));

                        FileProviderFactory fileFactory = new FileProviderFactory(outputPath);
                        fileFactory.getInstance(codeTemplate.getExtension()).create(codeTemplate, context, params, basePackage);
                    }
                }
            }
        }
    }

    private String getGenCode(String templateId, OnlFormHead formHead, Map<String, String> groupPathMap) {
        Map<String, Object> params = new HashMap<>();
        params.putAll(Defaults.getDefaultVariables());
        GlobalDataHelper instance = GlobalDataHelper.getInstance();
        params.putAll(instance.getVariables().getParams());

        final List<CodeTemplate> templatesList = new ArrayList<>();
        instance.getTemplates().getRoots().forEach(it -> it.getGroups().forEach(template -> templatesList.addAll(template.getTemplates())));

        final List<CodeTemplate> genTemplates = templatesList.stream().filter(it -> StringUtils.equals(it.getId(), templateId)).collect(Collectors.toList());

        // start your process

        for (CodeTemplate template : genTemplates) {
            VelocityContext velocityContext = new VelocityContext(BuilderUtil.transBean2Map(formHead));
            velocityContext.put("serialVersionUID", BuilderUtil.computeDefaultSUID(formHead.getModel(), formHead.getFields()));
            // $!dateFormatUtils.format($!now,'yyyy-MM-dd')
            velocityContext.put("dateFormatUtils", new org.apache.commons.lang.time.DateFormatUtils());
            if (StringUtils.isNotBlank(template.getSubPath())) {
                velocityContext.put("templateSubPath", template.getSubPath().replace("/", "."));
            }
//                    if (!StringUtils.isEmpty(basePackage)) {
//
//                    }
            params.put("basePackage", "com.redare.test");
            if (params != null && params.size() > 0) {
                for (Map.Entry<String, Object> entry : params.entrySet()) {
                    velocityContext.put(entry.getKey(), entry.getValue());
                }
            }
            String temp = VelocityUtil.evaluate(velocityContext, template.getTemplate());
//                String formattedSource =new Formatter().formatSource(temp);
            return temp;
        }
        return "";
    }

    /**
     * 模版组优先级排序
     */
    public class ComparatorUtil implements Comparator<CodeGroup> {

        @Override
        public int compare(CodeGroup o1, CodeGroup o2) {
            double level1 = o1.getLevel();
            double level2 = o2.getLevel();
            if (level1 > level2) {
                return 1;
            } else if (level1 < level2) {
                return -1;
            } else {
                return 0;
            }
        }
    }
}
